package com.starlink.client.ras.impl;

import cn.hutool.core.bean.BeanUtil;
import com.google.common.collect.Lists;
import com.starlink.client.ras.RasClient;
import com.starlink.client.ras.enums.RasUrlEnum;
import com.starlink.client.ras.helper.AccountInfoRequestHelper;
import com.starlink.client.ras.properties.RASProperties;
import com.starlink.client.ras.request.*;
import com.starlink.client.ras.response.*;
import com.starlink.common.enums.ErrorCode;
import com.starlink.common.exception.BusinessException;
import com.starlink.common.utils.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class RasClientImpl implements RasClient {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private AccountInfoRequestHelper accountInfoRequestHelper;
    @Autowired
    private RASProperties rasProperties;

    @Override
    public RasBaseResponse<Integer> wrap(WrapRequest request) {
        accountInfoRequestHelper.fillAccountInfo(request);
        return executeHttp(request, RasUrlEnum.wrap, RasBaseResponse.class);
    }

    @Override
    public RasBaseResponse<WrapAuditListResponse> wrapAuditList(WrapAuditListRequest request) {
        return executeHttp(request, RasUrlEnum.wrapAuditList, RasBaseResponse.class);
    }

    @Override
    public RasBaseResponse<ActivationSingleCodeActivationResponse> activationSingleCodeActivation(
            ActivationSingleCodeActivationRequest request) {
//        return executeHttp(request, RasUrlEnum.activationSingleCodeActivation, RasBaseResponse.class);
        // 构建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", loginAndGetToken());

        // 构建请求参数
        URI uri = buildUriWithParamsTwo(RasUrlEnum.activationSingleCodeActivation.getUrl(), request);

        // 发送请求
        HttpEntity<ActivationSingleCodeActivationRequest> entity = new HttpEntity<>(request, headers);
        ResponseEntity<RasBaseResponse<ActivationSingleCodeActivationResponse>> responseEntity =
                restTemplate.exchange(uri, HttpMethod.POST, entity,
                        new ParameterizedTypeReference<RasBaseResponse<ActivationSingleCodeActivationResponse>>() {});

        // 处理响应
        RasBaseResponse<ActivationSingleCodeActivationResponse> body = responseEntity.getBody();
        AssertUtil.assertNotNull(body, ErrorCode.INTER_ERR);
        AssertUtil.assertTrue(body.isSuc(), "RAS外部服务调用失败 原因：" + body.getMsg());
        AssertUtil.assertTrue(body.isBizSuc(), "RAS外部服务调用失败 原因：" + body.getMsg());

        return body;
    }


    @Override
    public RasBaseResponse<GoodsBindingResponse> goodsBinding(GoodsBindingRequest request) {
        return executeHttp(request, RasUrlEnum.goodsBinding, RasBaseResponse.class);
    }

    @Override
    public RasBaseResponse<GoodsListEvidenceResponse> goodsListEvidence(GoodsListEvidenceRequest request) {
        // 构建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", loginAndGetToken());

        // 构建请求参数
        URI uri = buildUriWithParams(RasUrlEnum.goodsListEvidence.getUrl(), request);

        // 发送请求
        HttpEntity<GoodsListEvidenceRequest> entity = new HttpEntity<>(request, headers);
        ResponseEntity<RasBaseResponse<GoodsListEvidenceResponse>> responseEntity =
                restTemplate.exchange(uri, HttpMethod.GET, entity,
                        new ParameterizedTypeReference<RasBaseResponse<GoodsListEvidenceResponse>>() {});

        // 处理响应
        RasBaseResponse<GoodsListEvidenceResponse> body = responseEntity.getBody();
        AssertUtil.assertNotNull(body, ErrorCode.INTER_ERR);
        AssertUtil.assertTrue(body.isSuc(), "RAS外部服务调用失败 原因：" + body.getMsg());
        AssertUtil.assertTrue(body.isBizSuc(), "RAS外部服务调用失败 原因：" + body.getMsg());

        return body;
    }

    private URI buildUriWithParams(String baseUrl, GoodsListEvidenceRequest request) {
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(rasProperties.getUrl() + baseUrl);
        BeanMap beanMap = BeanMap.create(request);
        beanMap.forEach((key, value) -> {
            if (value != null) {
                builder.queryParam(key.toString(), value.toString());
            }
        });
        return builder.build().encode().toUri();
    }

    private URI buildUriWithParamsTwo(String baseUrl, ActivationSingleCodeActivationRequest request) {
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(rasProperties.getUrl() + baseUrl);
        BeanMap beanMap = BeanMap.create(request);
        beanMap.forEach((key, value) -> {
            if (value != null) {
                builder.queryParam(key.toString(), value);
            }
        });
        return builder.build().encode().toUri();
    }
    @Override
    public RasBaseResponse<Integer> goodsAdd(GoodsAddRequest request) {
        accountInfoRequestHelper.fillAccountInfo(request);
        return executeHttp(request, RasUrlEnum.goodsAdd, RasBaseResponse.class);
    }

    @Override
    public RasBaseResponse<Map<Long, Integer>> batchGoodsAdd(List<GoodsAddRequest> request) {
        request.forEach(item->{
            accountInfoRequestHelper.fillAccountInfo(item);
        });
        return executeHttpPost(request, RasUrlEnum.batchGoodsAdd);
    }

    private RasBaseResponse<Map<Long, Integer>>  executeHttpPost(List<GoodsAddRequest> requests,
                                                                                RasUrlEnum urlEnum) {
        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", loginAndGetToken());

        URI uri = URI.create(rasProperties.getUrl() + urlEnum.getUrl());
        RasBaseResponse<Map<Long, Integer>> body = null;
        try {
            HttpEntity<List<GoodsAddRequest>> entity = new HttpEntity<>(requests, headers);
            ResponseEntity<RasBaseResponse<Map<Long, Integer>>> responseEntity = restTemplate.exchange(uri, HttpMethod.POST, entity, new ParameterizedTypeReference<RasBaseResponse<Map<Long, Integer>>>() {});
            AssertUtil.assertNotNull(responseEntity, ErrorCode.INTER_ERR);
            AssertUtil.assertNotNull(responseEntity.getBody(), ErrorCode.INTER_ERR);
            body = responseEntity.getBody();
            AssertUtil.assertTrue(body.isSuc(), "RAS外部服务调用失败 原因：" + body.getMsg());
            AssertUtil.assertTrue(body.isBizSuc(), "RAS外部服务调用失败 原因：" + body.getMsg());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.INTER_ERR, "调用RAS接口失败: " + e.getMessage());
        }
        return body;
    }



    /**
     * @param request
     * @param urlEnum
     * @param responseClass
     * @param <T>
     * @param <R>
     * @return
     */
    private <T extends RasBaseRequest, R extends RasBaseResponse> R executeHttp(T request,
                                                                                RasUrlEnum urlEnum,
                                                                                Class<R> responseClass) {
        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", loginAndGetToken());

        URI uri = URI.create(rasProperties.getUrl() + urlEnum.getUrl());
        if (urlEnum.getMethod() == HttpMethod.GET) {
            String url = rasProperties.getUrl() + urlEnum.getUrl();
            Map<String, Object> stringObjectMap = BeanUtil.beanToMap(request);
            List<String> param = Lists.newArrayList();
            stringObjectMap.forEach((key, value) -> {
                if (value != null) {
                    param.add(String.format("%s=%s", key, value));
                }
            });
            String collect = param.stream().collect(Collectors.joining("&"));
            uri = URI.create(url +"?"+ collect);
        }
        R body = null;
        try {
            HttpEntity<T> entity = new HttpEntity<>(request, headers);
            ResponseEntity<R> responseEntity = restTemplate.exchange(uri, urlEnum.getMethod(), entity, responseClass);
            AssertUtil.assertNotNull(responseEntity, ErrorCode.INTER_ERR);
            AssertUtil.assertNotNull(responseEntity.getBody(), ErrorCode.INTER_ERR);
            body = responseEntity.getBody();
            AssertUtil.assertTrue(body.isSuc(), "RAS外部外部服务调用失败 原因：" + body.getMsg());
            AssertUtil.assertTrue(body.isBizSuc(), "RAS外部外部服务调用失败 原因：" + body.getMsg());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.INTER_ERR, "调用RAS接口失败: " + e.getMessage());
        }
        return body;
    }

    /**
     * 获取登录态
     * @return
     */
    private String loginAndGetToken() {
        // 调用登录接口，获取登录响应
        LoginResponse loginResponse = restTemplate.postForObject(
                rasProperties.getUrl() + RasUrlEnum.login.getUrl(), // 登录接口的URL
                accountInfoRequestHelper.getLoginRequest(),
                LoginResponse.class
        );
        // 从登录响应中获取token
        return loginResponse.getToken();
    }
}
